home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Over 1,000 Windows 95 Programs
/
Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso
/
1249
/
eigenval.t
< prev
next >
Wrap
Text File
|
1997-04-18
|
14KB
|
790 lines
%
% "eigenval.t" computes algebraic eigenvalues
% using QR decomposition
%
% adapted from:
% "C Tools for Scientists and Engineers" by L. Baker
%
% Sample program for the T Interpreter by:
%
% Stephen R. Schmitt
% 962 Depot Road
% Boxborough, MA 01719
%
var macheps : real := 0.00000001
const DIM : int := 3
type rmatrix : array[DIM,DIM] of real
type ivector : array[DIM] of int
type rvector : array[DIM] of real
var A : rmatrix
program
var wr, wi : rvector
var z : rmatrix
var i : int
var iwork, cnt : ivector
put "array 1:"
A[0,0] := 2
A[0,1] := 2
A[0,2] := 1
A[1,0] := 1
A[1,1] := 3
A[1,2] := 1
A[2,0] := 1
A[2,1] := 2
A[2,2] := 2
print_matrix( A )
eigenvv( A, iwork, z, wr, wi, cnt )
put ""
put "eigenvalues for array 1:"
put ""
for i := 0...DIM-1 do
put complex_str( wr[i], wi[i] ), " it = ", cnt[i]
end for
put ""
put ""
put "array 2:"
A[0,0] := 2
A[0,1] := 4
A[0,2] := 4
A[1,0] := 0
A[1,1] := 3
A[1,2] := 1
A[2,0] := 0
A[2,1] := 1
A[2,2] := 3
print_matrix( A )
eigenvv( A, iwork, z, wr, wi, cnt )
put ""
put "eigenvalues for array 2:"
put ""
for i := 0...DIM-1 do
put complex_str( wr[i], wi[i] ), " it = ", cnt[i]
end for
put ""
put ""
put "array 3:"
A[0,0] := 5
A[0,1] := -4
A[0,2] := -7
A[1,0] := -4
A[1,1] := 2
A[1,2] := -4
A[2,0] := -7
A[2,1] := -4
A[2,2] := 5
print_matrix( A )
put ""
put "eigenvalues for array 3:"
put ""
eigenvv( A, iwork, z, wr, wi, cnt )
for i := 0...DIM-1 do
put complex_str( wr[i], wi[i] ), " it = ", cnt[i]
end for
put ""
put ""
put "array 4:"
A[0,0] := 1
A[0,1] := -1
A[0,2] := -1
A[1,0] := 1
A[1,1] := -1
A[1,2] := 0
A[2,0] := 1
A[2,1] := 0
A[2,2] := -1
print_matrix( A )
put ""
put "eigenvalues for array 4:"
put ""
eigenvv( A, iwork, z, wr, wi, cnt )
for i := 0...DIM-1 do
put complex_str( wr[i], wi[i] ), " it = ", cnt[i]
end for
end program
%
% compute eigenvalues and eigenvectors of a matrix
%
procedure eigenvv( var a : rmatrix,
var iwork : ivector,
var z : rmatrix,
var wr, wi : rvector,
var cnt : ivector )
var ierr : int
elmhes( a, iwork )
eltran( a, iwork, z )
hqr2( a, wr, wi, z, ierr, cnt )
if ierr ~= 0 then
put "ierr = ", ierr
end if
end procedure
%
% convert a general matrix to Hessenberg form
%
procedure elmhes( var a : rmatrix, var intar : ivector )
var i, j, m, la, kp1, mm1, mp1 : int
var x, y : real
la := DIM - 2
kp1 := 1
if la < kp1 then
return
end if
for m := kp1...la do
mm1 := m - 1
x := 0.0
i := m
for j := m...DIM-1 do
if rabs( a[j,mm1] ) > rabs( x ) then
x := a[j,mm1]
i := j
end if
end for
intar[m] := i
if i ~= m then
for j := mm1...DIM-1 do
y := a[i,j]
a[i,j] := a[m,j]
a[m,j] := y
end for
for j := 0...DIM-1 do
y := a[j,i]
a[j,i] := a[j,m]
a[j,m] := y
end for
end if
if x ~= 0.0 then
mp1 := m + 1
for i := mp1...DIM-1 do
y := a[i,mm1]
if y ~= 0.0 then
y := y / x
a[i,mm1] := y
for j := m...DIM-1 do
a[i,j] := a[i,j] - y * a[m,j]
end for
for j := 0...DIM-1 do
a[j,m] := a[j,m] + y * a[j,i]
end for
end if
end for
end if
end for
end procedure
%
% create transform matrix using results of elmhes
%
procedure eltran( var a : rmatrix,
var intar : ivector,
var z : rmatrix )
var i, j, k, l, kl, mn, mp, mp1 : int
% set z to identity matrix
for i := 0...DIM-1 do
for j := 0...DIM-1 do
z[i,j] := 0.0
end for
z[i,i] := 1.0
end for
kl := DIM - 2
if kl < 1 then
return
end if
for decreasing i := DIM-2...1 do
j := intar[i]
for k := i+1...DIM-1 do
z[k,i] := a[k,i-1]
end for
if i ~= j then
for k := i...DIM-1 do
z[i,k] := z[j,k]
z[j,k] := 0.0
end for
z[j,i] := 1.0
end if
end for
end procedure
%
% apply QR method to Hessenberg matrix
%
procedure hqr2( var h : rmatrix,
var wr, wi : rvector,
var vecs : rmatrix,
var ierr : int,
var cnt : ivector )
var i, j, k, l, m, ii, jj, kk, mm, na, nm, nn, its, mpr, enm2, en : int
var it1, it2, itlim : int
var p, q, r, s, t, w, x, y, z, ra, sa, vi, vr, norm : real
var xr, yr, xi, yi, zr, zi : real
var notlast : boolean
label nextw:
label nextit:
label break1:
it1 := 10
it2 := 20
itlim := 30
ierr := 0
norm := 0.0
k := 0
for i := 0...DIM-1 do
for j := k...DIM-1 do
norm := norm + rabs( h[i,j] )
end for
k := i
cnt[i] := 0
end for
assert norm > 0.0
en := DIM-1
t := 0.0
nextw:
watch( en )
if en >= 0 then
its := 0
na := en - 1
enm2 := na - 1
nextit:
for decreasing l := en...1 do
s := rabs( h[l-1,l-1] ) + rabs( h[l,l] )
if s = 0.0 then
s := norm
end if
if rabs( h[l,l-1] ) <= s * macheps then
goto break1
end if
end for
l := 0
break1:
x := h[en,en]
watch( l )
if l = en then % found single a root
wr[en] := x + t
wi[en] := 0.0
h[en,en] := x + t
cnt[en] := its
en := na
goto nextw
end if
y := h[na,na]
w := h[en,na] * h[na,en]
if l ~= na then
if its = itlim then
cnt[en] := 31
ierr := en
return
end if
if its = it1 or its = it2 then
t := t + x
for i := 0...en do
h[i,i] := h[i,i] - x
end for
s := rabs( h[en,na] ) + rabs( h[na,en-2] )
x := 0.75 * s
y := x
w := -0.4375 * s * s
end if
incr its
for decreasing m := en-2...l do
mm := m + 1
z := h[m,m]
r := x - z
s := y - z
p := ( r * s - w ) / ( h[mm,m] ) + h[m,mm]
q := h[mm,mm] - z - r - s
r := h[m+2,mm]
s := rabs( p ) + rabs( q ) + rabs( r )
p := p / s
q := q / s
r := r / s
if m = l then
exit
end if
if rabs( h[m,m-1] ) * ( rabs( q ) + rabs( r ) ) <=
macheps * rabs( p ) *
( rabs( h[m-1,m-1] ) + rabs( z ) + rabs( h[mm,mm] ) )
then
exit
end if
end for
for i := m+2...en do
h[i,i-2] := 0.0
end for
for i := m+3...en do
h[i,i-3] := 0.0
end for
for k := m...na do
notlast := k ~= na
if k ~= m then
p := h[k,k-1]
q := h[k+1,k-1]
if notlast then
r := h[k+2,k-1]
else
r := 0.0
end if
x := rabs( r ) + rabs( q ) + rabs( p )
if x = 0.0 then
exit
end if
p := p / x
q := q / x
r := r / x
end if
s := sqrt( p * p + q * q + r * r )
if p < 0.0 then
s := -s
end if
if k ~= m then
h[k,k-1] := -s * x
elsif l ~= m then
h[k,k-1] := -h[k,k-1]
end if
p := p + s
x := p / s
y := q / s
z := r / s
q := q / p
r := r / p
% row modification
for j := k...DIM-1 do
p := h[k,j] + q * h[k+1,j]
if notlast then
p := p + r * h[k+2,j]
h[k+2,j] := h[k+2,j] - p * z
end if
h[k+1,j] := h[k+1,j] - p * y
h[k,j] := h[k,j] - p * x
end for
% column modification
if k + 3 < en then
j := k + 3
else
j := en
end if
for i := 0...j do
p := x * h[i,k] + y * h[i,k+1]
if notlast then
p := p + z * h[i,k+2]
h[i,k+2] := h[i,k+2] - p * r
end if
h[i,k+1] := h[i,k+1] - p * q
h[i,k] := h[i,k] - p
end for
% accumulate
for i := 0...DIM-1 do
p := x * vecs[i,k] + y * vecs[i,k+1]
if notlast then
p := p + z * vecs[i,k+2]
vecs[i,k+2] := vecs[i,k+2] - p * r
end if
vecs[i,k+1] := vecs[i,k+1] - p * q
vecs[i,k] := vecs[i,k] - p
end for
end for % k
goto nextit
end if % l ~= na
% else two roots were found
p := 0.5 * ( y - x )
q := p * p + w
z := sqrt( rabs( q ) )
x := x + t
h[en,en] := x
h[na,na] := y + t
cnt[en] := -its
cnt[na] := its
if q >= 0.0 then % real pair of roots
if p < 0.0 then
z := p - z
else
z := p + z
end if
wr[na] := x + z
wr[en] := wr[na]
if z ~= 0.0 then
s := x - w / z
wr[en] := s
end if
wi[en] := 0.0
wi[na] := 0.0
x := h[en,na]
s := rabs( x ) + rabs( z )
p := x / s
q := z / s
r := sqrt( p * p + q * q )
p := p / r
q := q / r
for j := na...DIM-1 do
z := h[na,j]
h[na,j] := q * z + p * h[en,j]
h[en,j] := q * h[en,j] - p * z
end for
for i := 0...en do
z := h[i,na]
h[i,na] := q * z + p * h[i,en]
h[i,en] := q * h[i,en] - p * z
end for
for i := 0...DIM-1 do
z := vecs[i,na]
vecs[i,na] := q * z + p * vecs[i,en]
vecs[i,en] := q * vecs[i,en] - p * z
end for
else % complex pair of roots
wr[en] := x + p
wr[na] := x + p
wi[na] := z
wi[en] := -z
end if
decr en
decr en
goto nextw
end if % en >= 0
% all eigenvalues have been found
end procedure
%=====================================================================
% some utility functions
%=====================================================================
%
% return the absolute value of a real number
%
function rabs( x : real ) : real
var rv : real
if x < 0.0 then
rv := -x
else
rv := x
end if
return rv
end function
%
% print a real 2D matrix
%
procedure print_matrix( var a : rmatrix )
var i, j, btm, top, count : int := 0
put ""
loop
exit when btm >= DIM
if DIM > btm + 8 then
top := btm + 8
else
top := DIM
end if
put "matrix columns ", btm, " to ", top - 1
for j := 0...DIM-1 do
for i := btm...top-1 do
put a[j,i]:15:6:3...
end for
put ""
end for
btm := btm + 8
end loop
end procedure
%
% convert complex number to a string
%
function complex_str( re, im : real ) : string
var s : string
if im >= 0.0 then
s := erealstr(re,15,6,3) & " +" & erealstr(im,13,6,3) & "j"
else
im := -im
s := erealstr(re,15,6,3) & " -" & erealstr(im,13,6,3) & "j"
end if
return s
end function